package cn.topevery.garden.dal.util;

import hw.topevery.framework.GeometryHelper;
import hw.topevery.framework.util.LogUtil;
import org.locationtech.jts.geom.Geometry;

public class GeomHelper {
    /// <summary>
    /// 获取两点距离
    /// </summary>
    /// <param name="x1"></param>
    /// <param name="x2"></param>
    /// <param name="y1"></param>
    /// <param name="y2"></param>
    /// <returns></returns>
    public static double getPointDistance(double x1, double x2, double y1, double y2) {
        double xx = x1 - x2;
        double yy = y1 - y2;
        return Math.sqrt(xx * xx + yy * yy);
    }

    /// <summary>
    /// 根据点获取点面距离
    /// </summary>
    /// <param name="sourceGemo"></param>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <returns></returns>
    public static double getGeomDistanceByXY(Geometry sourceGemo, double x, double y) {
        double result = Double.MIN_VALUE;
        if (sourceGemo != null) {
            boolean isEmpty = sourceGemo.isEmpty();
            if (!isEmpty && (x > 0 && y > 0)) {
                Geometry targetGeom = getPointGeom(sourceGemo.getSRID(), x, y);
                result = getGeomDistance(sourceGemo, targetGeom);
            }
        }
        return result;
    }

    private static Geometry getPointGeom(int srId, double x, double y) {
        String wellKnownText = String.format("POINT(%s %s)", x, y);
        Geometry geometry = GeometryHelper.getGeometry(wellKnownText, srId);
        return geometry;
    }

    /// <summary>
    /// 获取两个面间的距离
    /// </summary>
    /// <param name="sourceGemo"></param>
    /// <param name="targetGeom"></param>
    /// <returns></returns>
    public static double getGeomDistance(Geometry sourceGemo, Geometry targetGeom) {
        double dist = sourceGemo.distance(targetGeom);
        return dist;
    }

    /// <summary>
    /// 点是否在某范围内，
    /// </summary>
    /// <param name="sourceGemo">范围</param>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <param name="offset">偏移量</param>
    /// <returns></returns>
    public static boolean inGeom(Geometry areaGemo, double x, double y, double offset) {
        boolean res = false;
        Geometry pointGeom = getPointGeom(areaGemo.getSRID(), x, y);

        if (areaGemo.getGeometryType().equalsIgnoreCase(Geometry.TYPENAME_GEOMETRYCOLLECTION)) {
            res = inGeomCollection(areaGemo, x, y, offset);
        } else {
            res = areaGemo.contains(pointGeom);
            if (!res && offset > 0) {
                res = areaGemo.distance(pointGeom) <= offset;
            }
        }
        return res;
    }

    /// <summary>
    /// 点是否在某范围内，
    /// </summary>
    /// <param name="sourceGemo">范围</param>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <param name="offset">偏移量</param>
    /// <returns></returns>
    public static boolean inGeom(Geometry areaGemo, double x, double y) {
        Geometry pointGeom = getPointGeom(areaGemo.getSRID(), x, y);
        boolean res = false;
        if (areaGemo.getGeometryType().equalsIgnoreCase(Geometry.TYPENAME_GEOMETRYCOLLECTION)) {
            res = inGeomCollection(areaGemo, x, y);
        } else {
            res = areaGemo.contains(pointGeom);
        }
        return res;
    }

    private static boolean inGeomCollection(Geometry areaGemo, double x, double y, double offset) {
        boolean res = false;
        try {
            int countRes = 0;
            int geomNum = areaGemo.getNumGeometries();
            for (int i = 0; i < geomNum; i++) {
                Geometry g = areaGemo.getGeometryN(i);
                boolean ress = inGeom(g, x, y, offset);
                if (ress) {
                    countRes++;
                }
            }
            res = countRes > 0;
        } catch (Exception ex) {
            LogUtil.error(ex.getMessage(), ex);
        }
        return res;
    }

    private static boolean inGeomCollection(Geometry areaGemo, double x, double y) {
        boolean res = false;
        try {
            int countRes = 0;
            int geomNum = areaGemo.getNumGeometries();
            for (int i = 0; i < geomNum; i++) {
                Geometry g = areaGemo.getGeometryN(i);
                boolean ress = inGeom(g, x, y);
                if (ress) {
                    countRes++;
                }
            }
            res = countRes > 0;
        } catch (Exception ex) {
            LogUtil.error(ex.getMessage(), ex);
        }
        return res;
    }
}
